import uuid
import re
import requests
import json
from typing import Optional
from io import BytesIO
from docx import Document
from docx.shared import RGBColor
from docx.shared import Inches
from docx.shared import Pt
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH

from datetime import datetime,timedelta
from bisheng.api.jsj_api.model.alarm_record import AlarmRecordDao, AlarmRecord
from bisheng.api.jsj_api.model.fault_work_repair import FaultWorkRepair, FaultWorkRepairDao
from bisheng.api.jsj_api.model.fault_work_ticket import FaultWorkTicket, FaultWorkTicketDao
from bisheng.api.jsj_api.model.fault_work_order import FaultWorkOrder, FaultWorkOrderDao
from bisheng.api.jsj_api.utils.simple_minio_client import SimpleMinioClient
from bisheng.api.jsj_api.model.metro_fault import ConfigDao

class UatService:

    def __init__(self):
        self.qdsq2_url = "http://172.27.174.129:8001/qdsg2/service"
        pass

    def create_fault_work_ticket_new(self, group_id:str) -> str:
        task_number,plan_id = self.select_task_number(group_id)
        request_data = self.create_ticket_request_data(group_id,task_number,plan_id)
        # response = self.call_external_api(self.qdsq2_url, request_data)
        # response = json.loads(response)
        response = {}
        if response is None:
            return ""
        if response.get("isSuccess") == 1:
            print("创建工作票Success!")
            # 生成工作票单据
            self.create_fwt(group_id, task_number)
            return task_number
        else:
            print("创建工作票Failed.")
            error_message = response.get("msg", "Unknown error")
            print(f"Error message: {error_message}")
            return ""



    def create_fault_work_repair_new(self,group_id:str) -> str :
        request_data = self.create_repair_request_data(group_id)
        # response = self.call_external_api(self.qdsq2_url, request_data)
        response = {}
        # response = json.loads(response)
        if response.get("isSuccess") == 1:
            print("创建维修计划Success!")
            plan_num = response.get("planNum")
            task_number = response.get("taskNumber")
            plan_id = response.get("planId")
            # 生成维修计划单据
            self.create_fwr(group_id,plan_num,task_number,plan_id)
            return plan_num
        else:
            print("创建维修计划Failed.")
            error_message = response.get("message", "Unknown error")
            print(f"Error message: {error_message}")
            return ""


    @staticmethod
    def create_ticket_request_data(group_id:str,task_number:str,plan_id:str) -> dict:
        alarm_records = AlarmRecordDao.get_alarm_record_by_group_id(group_id)
        if alarm_records is None or len(alarm_records) == 0:
            print("获取告警数据异常")
            return {}
        now = datetime.now()
        now_str = now.strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间

        alarm_time = alarm_records[0].alarm_time
        today = alarm_time.strftime("%Y-%m-%d")
        alarm_time_str = alarm_time.strftime("%Y-%m-%d %H:%M:%S")
        # 3. 格式化 alarm_time 和计算 3 小时后的时间
        future_time = alarm_time + timedelta(hours=3)
        future_time_formatted = future_time.strftime("%Y-%m-%d %H:%M:%S")

        request_data = {
            "serviceId": "S_AI_SG_BD_01",
            "data": {
                "substation": alarm_records[0].station,
                "workDate": today,
                "stoStartTime": alarm_time_str,
                "stoEndTime": future_time_formatted,
                "leader": "李德志",
                "leaderPhone": "13560792616",
                "workers": "苗席",
                "workerNum": "1",
                "isolationSwitch": "断开：DC1500V馈线断路器211、212、213、214、210 ，确认分位；DC1500V进线断路器201、202，确认分位；35kV馈线断路器322、324、325，确认分位；$$$拉开：DC1500V馈线隔离开关2111、2121、2131、2141，确认分位；DC1500V负极隔离开关2011、2021，确认分位；35kV馈线隔离开关3221、3241、3251，确认分位,$$$将DC1500V断路器小车201、202摇至试验位。",
                "groundWirePosition": "在35kV馈线断路器322、324、325 馈出线端验明无电后，以维护接地的方式合3221E、3241E、3251E地刀，确认合位；合322、324、325断路器，确认合位；并在“闭锁紧急分闸”闭锁杆上加挂机械锁；$$$在1#、2#整流变压器高低压侧分别验明无电并充分放电后，在高压侧各挂一组三相交流接地线，在低压侧各挂两组三相交流接地线；$$$在1#、2#整流器直流侧分别验明无电并充分放电后，在直流侧正负极母排各挂一组直流接地线；$$$在1#、2#整流器进线侧分别验明无电并充分放电后，在进线侧各挂一组三相交流接地线。$$$共八组三相交流接地线、四组直流接地线",
                "markCardPosition": "在35kV馈线开关柜322、324、325悬挂“禁止分闸”标示牌；并将相邻带电设备设置遮拦，悬挂“止步，高压危险”警示牌；$$$在直流开关柜201、202、210，负极柜2011、2021处挂“禁止合闸”标示牌；$$$在1#、2#整流器和1#、2#整流变压器栅栏处分别挂“在此工作”标示牌；$$$用警示带将1#、2#整流器柜作业区域分别与其它非作业区域封闭隔离，各留一个人员出入口。",
                "attentionElectricDevice": "35kV开关柜除322、324、325外，其余均带电运行。",
                "otherSafeguard": "作业人员劳保用品穿戴齐全；$$$作业前，断开1#、2#整流器及1#、2#整流变压器温控仪控制箱内的二次电源，并断开322、324、325开关柜二次室内储能电源；$$$作业时勿走错作业间隔，1#、2#整流器作业时不得随意离开封闭隔离区域；$$$作业完毕出清现场、恢复设备正常状态。",
                "recCreator": "06014346",
                "recCreateTime": now_str,
                "archiveFlag": "0",
                "deleteFlag": "0",
                "taskArea":  alarm_records[0].station,
                "taskContent": "整流机组小修（年检）测试测试",
                "finishAttentionElectricDevice": "35kV开关柜除_______、_______、_______外，其余均带电运行。",
                "finishGroundWirePosition": "已在35kV馈线断路器_______、_______、_______馈出线端验明无电后，以维护接地的方式合_______、_______、_______地刀，确认合位；合_______、_______、_______断路器，确认合位；并在“闭锁紧急分闸”闭锁杆上加挂机械锁；$$$已在1#、2#整流变压器高低压侧分别验明无电并充分放电后，在高压侧各挂一组三相交流接地线，在低压侧各挂两组三相交流接地线；$$$已在1#、2#整流器直流侧分别验明无电并充分放电后，在直流侧正负极母排各挂一组直流接地线；$$$已在1#、2#整流器进线侧分别验明无电并充分放电后，在进线侧各挂一组三相交流接地线。$$$共_____组三相交流接地线、_____组直流接地线",
                "finishIsolationSwitch": "已断开：DC1500V馈线断路器_______、_______、_______、_______、_______，确认分位；DC1500V进线断路器_______、_______，确认分位；35kV馈线断路器_______、_______、_______，确认分位；$$$已拉开：DC1500V馈线隔离开关_______、_______、_______、_______，确认分位；DC1500V负极隔离开关_______、_______，确认分位；35kV馈线隔离开关_______、_______、_______，确认分位；$$$已将DC1500V断路器小车_______、_______摇至试验位。",
                "finishMarkCardPosition": "已在35kV馈线开关柜_______、_______、_______悬挂“禁止分闸”标示牌；并将相邻带电设备设置遮拦，悬挂“止步，高压危险”警示牌；$$$已在直流开关柜_______、_______、_______，负极柜_______、_______处挂“禁止合闸”标示牌；$$$已在1#、2#整流器和1#、2#整流变压器栅栏处分别挂“在此工作”标示牌；$$$已用警示带将1#、2#整流器柜作业区域分别与其它非作业区域封闭隔离，各留一个人员出入口。",
                "finishOtherSafeguard": "作业人员劳保用品已穿戴齐全；$$$作业前，已断开1#、2#整流器及1#、2#整流变压器温控仪控制箱内的二次电源，并已断开322、324、325开关柜二次室内储能电源；$$$作业时未走错作业间隔，1#、2#整流器作业时不得随意离开封闭隔离区域；$$$作业完毕已出清现场、恢复设备正常状态。",
                "lineId": "20210311line4294bc5974104fba2008",
                "workStatus": "1",
                "taskNumber": task_number,
                "planId": plan_id
            }
        }
        print(request_data)
        return request_data

    @staticmethod
    def create_repair_request_data(group_id:str) -> Optional[dict]:
        alarm_records = AlarmRecordDao.get_alarm_record_by_group_id(group_id)
        if alarm_records is None or len(alarm_records) == 0:
            print("获取告警数据异常")
            return {}
        now = datetime.now()
        now3 = now+timedelta(hours=3)
        now_str = now.strftime("%Y-%m-%d %H:%M:%S")
        now3_str = now3.strftime("%Y-%m-%d %H:%M:%S")
        now_time_str = now.strftime("%H:%M")# 获取当前时间
        now3_time_str = now3.strftime("%H:%M")
        # alarm_time = alarm_records[0].alarm_time
        today = now.strftime("%Y-%m-%d")
        request_data = {
            "serviceId":"S_AI_SG_JH_01",
                "data":{
                    "lineId":"20210311line4294bc5974104fba2008",
                    "isSpan":"0",
                    "planDateType":"02",
                    "taskQuality":"10",
                    "taskDate":today,
                    "taskTime":f"{now_time_str}-{now3_time_str}",
                    "taskStartTime":now_str,
                    "taskEndTime":now3_str,
                    "constructionGrade":"03",
                    "unittype":"1",
                    "constructionUnit":"0620980",
                    "taskPrincipal":"20210621abcd483795b08685d1003325",#需要李德志的
                    "principalPhone":"13560792616",
                    "planApplicant":"06014274",
                    "applicantPhone":"陈鑫17569113102",
                    "isInvolveLine":"0",
                    "isInvolveBase":"0",
                    "taskAreaSupplement":alarm_records[0].station,
                    "taskContent":alarm_records[0].description,
                    "askPlace":"06202308tb67443aa1e849cb536d0022",
                    "remPlace":"06202308tb67443aa1e849cb536d0022",
                    "assistStations":alarm_records[0].station,
                    "electricArrangement":"",
                    "electricType":"3",
                    "safeguard":"1、穿戴安全防护用品;2、现场防护",
                    "safeguardSup":"",
                    "isBlock":"0",
                    "isCarBlock":"0",
                    "isFirework":"0",
                    "remark":"1、作业前报6号线电环调度（电力）、场段运维调度;2、作业期间抓马山车辆段牵混所整流机组、再生制动能量吸收装置退出运行，DC1500V停电;3、作业期间PSCADA刷出相应报文，供电智慧调度系统工作站刷出相应报文，场段综合监控工作站刷出相应报文",
                    "joinRemark":"",
                    "planStatus":"5",
                    "isTemplate":"0",
                    "isValid":"1",
                    "recCreator":"06014274",
                    "recCreateTime":now_str,
                    "archiveFlag":"0",
                    "deleteFlag":"0",
                    "temporaryPoint":"0",
                    "isLimitedSpace":"0",
                    "applyResonType":"GZCL",
                    "electricTypeSup":"3",
                    "isHighWork":"0"
                }
        }
        print(request_data)
        return request_data



    @staticmethod
    def call_external_api(api_url, request_data):
        """
        调用外部系统接口，并处理返回结果。
        Args:
            api_url (str): 接口的 URL 地址。
            request_data (dict): 请求的 JSON 数据。
        Returns:
            dict:  如果调用成功，返回接口返回的 JSON 数据；
                   如果调用失败，返回包含错误信息的字典。  例如: `{"error": "Request failed", "message": "...", "status_code": 500}`
        """
        try:
            model_id = ConfigDao.get_config_by_key("get_suggest_question_model_id").value
            headers = {'Content-Type': 'application/json'}
            response = requests.post(api_url, data=json.dumps(request_data), headers=headers)
            response.raise_for_status()  # 抛出 HTTPError 异常，处理非 200 状态码
            return response.json()  # 将响应内容解析为 JSON
        except Exception as e:
            print(f"An unexpected error occurred: {e}")  # 捕获所有其他异常
            return {"error": "调用api异常", "message": str(e)}

    @staticmethod
    def save_alarm_end_time(group_id:str, alarm_end_time:str):
        datetime_object = datetime.strptime(alarm_end_time, "%Y-%m-%d %H:%M:%S")
        return AlarmRecordDao.update_alarm_end_time(group_id,datetime_object)

    @staticmethod
    def save_alarm_stage(group_id:str,stage:str):
        return AlarmRecordDao.update_alarm_stage(group_id,stage)

    @staticmethod
    def create_fwr(group_id:str, plan_num:str, task_number:str, plan_id:str):
        fault_work_repair = FaultWorkRepair(
            group_id=group_id,
            line="6号线",
            code=plan_num,
            task_number = task_number,
            plan_id = plan_id
        )
        fault_work_repair = FaultWorkRepairDao.create_fault_work_repair(fault_work_repair)
        fwr = fault_work_repair.dict()
        return fwr

    @staticmethod
    def select_task_number(group_id:str):
        fwr = FaultWorkRepairDao.get_lastest_repair_by_group_id(group_id)
        return fwr.task_number,fwr.plan_id

    @staticmethod
    def create_fwt(group_id:str,task_name:str):
        alarm_records = AlarmRecordDao.get_alarm_record_by_group_id(group_id)
        alarm_record = alarm_records[0]
        now = datetime.now()
        now_str = now.strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间
        formatted_date = now.strftime("%m%d")
        alarm_time = alarm_records[0].alarm_time
        today = alarm_time.strftime("%Y-%m-%d")
        fault_work_ticket = FaultWorkTicket(
            group_id=group_id,
            work_address=alarm_record.station,
            work_content=alarm_record.description,
            work_start_time=f"{today} 11:00:00",
            work_end_time=f"{today} 14:30:00",
            work_leader="李德志（四）",
            work_leader_phone="13560792616",
            work_member="李珂（四）",
            work_person_num=2,
            work_command=f"[2025](运营一中心-工电维保部)-({formatted_date})-01",
            code=task_name
        )
        fwt = FaultWorkTicketDao.create_fault_work_ticket(fault_work_ticket)
        return fwt




    @staticmethod
    def create_fault_work_order_new(group_id,chat_id):
        alarm_records = AlarmRecordDao.get_alarm_record_by_group_id(group_id)
        if alarm_records:
            # alarm_record = alarm_records[0]
            now = datetime.now()

            today = now.strftime("%Y-%m-%d")

            fault_work_order = FaultWorkOrderDao.get_fault_work_order_by_group_id_chat_id(group_id,chat_id)

            if fault_work_order is None:

                # 应该是查询出来。目前先写死
                fault_work_order = FaultWorkOrder(
                    group_id=group_id,
                    chat_id=chat_id,
                    type='故障',
                    child_type="故障",
                    status="未处理",
                    maintenance_department="18480400",
                    repair_department="18480700",
                    kind="变电",
                    professional_kind="变电",
                    fault_level="B级",
                    self_inspection="非自检",
                    plan_start_time=f"{today} 11:00:00",
                    plan_end_time=f"{today} 14:30:00",
                    code="1695100"
                )
                fault_work_order = FaultWorkOrderDao.create_fault_work_order(fault_work_order)
            fwo = fault_work_order.dict()
            return fwo

        return {}


    @staticmethod
    def create_word_with_images(content):
        """
        使用 #1...#1 和 #2...#2 作为标题和段落标题定界符来创建 Word 文档。

        Args:
            content: 包含标记的文本内容的字符串。

        Returns:
            MinIO 的 URL
        """

        document = Document()

        # 添加自定义样式
        styles = document.styles

        # 修改 Title 样式（黑色加粗）
        title_style = styles["Title"]
        title_style.font.color.rgb = RGBColor(0, 0, 0)
        title_style.font.bold = True

        # 创建 Heading 2 Custom 样式（黑色加粗）
        heading2_style = styles.add_style("Heading 2 Custom", WD_STYLE_TYPE.PARAGRAPH)
        heading2_style.base_style = styles["Heading 2"]
        heading2_style.font.size = Pt(14)
        heading2_style.font.bold = True
        heading2_style.font.color.rgb = RGBColor(0, 0, 0)

        def add_paragraph_with_style(text, style=None, alignment=None, bold=False):
            """
            添加带有指定样式的段落。
            Args:
                text: 段落文本。
                style: 段落样式。
                alignment: 对齐方式。
                bold: 是否加粗。
            """
            paragraph = document.add_paragraph(text, style)
            paragraph.style.font.color.rgb = RGBColor(0, 0, 0)  # 始终设置为黑色
            paragraph.style.font.bold = bold  # 根据参数决定是否加粗
            if alignment:
                paragraph.alignment = alignment
            return paragraph

        # 使用正则表达式查找标题和段落标题
        title_pattern = r"#1(.*?)#1"
        section_title_pattern = r"#2(.*?)#2"

        # 分割内容
        parts = re.split(f"({title_pattern}|{section_title_pattern}|\[.*?\])", content)

        for part in parts:
            if part is None:
                continue

            part = part.strip()

            if not part:
                continue

            if re.match(title_pattern, part):
                # 一级标题（黑色加粗）
                title_text = re.search(title_pattern, part).group(1).strip()
                add_paragraph_with_style(title_text, style="Title", alignment=WD_ALIGN_PARAGRAPH.CENTER, bold=True)
            elif re.match(section_title_pattern, part):
                # 二级标题 (章节标题)（黑色加粗）
                chapter_title_text = re.search(section_title_pattern, part).group(1).strip()
                add_paragraph_with_style(chapter_title_text, style="Heading 2 Custom", bold=True)
            elif re.match(r'\[(.*?)\]', part):
                # 图片 URL
                image_url = part[1:-1]  # 提取 URL，去掉方括号
                try:
                    response = requests.get(image_url, stream=True)
                    response.raise_for_status()
                    image_stream = BytesIO(response.content)
                    document.add_picture(image_stream, width=Inches(5))
                except requests.exceptions.RequestException as e:
                    print(f"Error downloading image from {image_url}: {e}")
                    document.add_paragraph(f"图片加载失败: {image_url}")
            else:
                # 普通文本（黑色）
                add_paragraph_with_style(part, bold=False)

        # 保存 Word 文档到内存
        word_stream = BytesIO()
        document.save(word_stream)
        word_stream.seek(0)



        # 上传到 MinIO
        filename = uuid.uuid4()  # 生成一个随机 UUID
        object_name = "alarm_report_docx/" + str(filename) + ".docx"  # OSS 上的对象名称 (包含路径和扩展名)
        SimpleMinioClient().upload_file_by_io("jsj-bucket", object_name, word_stream)

        # 构建下载链接
        download_url = SimpleMinioClient().generate_download_url("jsj-bucket", object_name)

        return download_url







